package my.graduation.mapper;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import my.graduation.constant.ExamRecordStatusConstant;
import my.graduation.constant.ExamScheStatusConstant;
import my.graduation.constant.RegRecordStatusConstant;
import my.graduation.constant.RegScheStatusConstant;
import my.graduation.dto.*;
import my.graduation.entity.*;
import my.graduation.enums.HttpCodeEnums;
import my.graduation.result.Result;
import my.graduation.service.ExaminationRecordService;
import my.graduation.util.ExamQueueManager;
import my.graduation.vo.AlertPaidVO;
import my.graduation.vo.DataVO;
import my.graduation.vo.ExaminationRecordVO;
import my.graduation.vo.RegistrationRecordVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Collectors;

/**
 * @Author: RavenLyn
 * @Date: 2025-02-26
 */
@Service
public class ExaminationRecordServiceImpl extends ServiceImpl<ExaminationRecordMapper, ExaminationRecord> implements ExaminationRecordService {

    @Autowired
    private ExaminationItemMapper examItemMapper;

    @Autowired
    private ExaminationRecordMapper examRecordMapper;

    /**
     * 医生给患者开检查单
     * @param dto
     * @return
     */
    @Override
    public Result addRecord(PrescribeDto dto) {
        System.out.println(dto.getDepartmentId());
        System.out.println(dto.getClinicId());
        System.out.println(dto.getExamItemId());
        System.out.println(dto.getPreDoctorId());
        System.out.println(dto.getPatientId());
        if(dto.getDepartmentId() != null &&
                dto.getClinicId() != null &&
                dto.getExamItemId() != null &&
                dto.getPreDoctorId() != null &&
                dto.getPatientId() != null){
            //存入（id，患者id、医生id、科室id、门诊id、检查状态、检查费用）
            ExaminationItem examItem = examItemMapper.selectById(dto.getExamItemId()); // 费用获取
            ExaminationRecord newOne = new ExaminationRecord();
            newOne.setClinicId(dto.getClinicId());
            newOne.setDepartmentId(dto.getDepartmentId());
            newOne.setExamItemId(dto.getExamItemId());
            newOne.setPreDoctorId(dto.getPreDoctorId()); //开单医生id
            newOne.setPatientId(dto.getPatientId());
            newOne.setStatus(ExamRecordStatusConstant.UNPAID);
            newOne.setFee(examItem.getFee());
            save(newOne);
            return Result.success();
        }else {
            return Result.error(HttpCodeEnums.INFO_IS_BLANK);
        }
    }

    /**
     * 患者查询患者预约记录 (patientId + status == unpaid)
     * @param dto
     * @return
     */
    @Override
    public Result<List<ExaminationRecord>> patGetUnpaidlist(ExamRecordDto dto) {
        if(dto.getPatientId() != null){
            List<ExaminationRecord> list = list(Wrappers.<ExaminationRecord>lambdaQuery()
                    .eq(ExaminationRecord::getPatientId, dto.getPatientId())
                    .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.UNPAID));
            return Result.success(list);
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 患者查询所有检查预约记录 (patientId)
     * @param dto
     * @return
     */
    @Override
    public Result<List<ExaminationRecord>> patGetAlllist(ExamRecordDto dto) {
        if(dto.getPatientId() != null){
            List<ExaminationRecord> list = list(Wrappers.<ExaminationRecord>lambdaQuery()
                    .eq(ExaminationRecord::getPatientId, dto.getPatientId()));
            return Result.success(list);
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 获取当前的检查预约记录   使用orderId和patientId查询支付成功后的订单
     * @param dto
     * @return
     */
    @Override
    public Result<ExaminationRecord> getExamCurrentRecord(ExamRecordDto dto) {
        // orderId  patientId
        if (dto.getOrderId() != null && dto.getPatientId() != null) {
            ExaminationRecord one = getOne(Wrappers.<ExaminationRecord>lambdaQuery()
                    .eq(ExaminationRecord::getOrderId, dto.getOrderId())
                    .eq(ExaminationRecord::getPatientId, dto.getPatientId()));

            if(one != null){
                System.out.println(one.getPayTime());
                return Result.success(one);
            }else {
                return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
            }
        } else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 退款 更新 status = 3
     * @param orderId
     * @param status
     * @return
     */
    @Override
    public Boolean updateStatus(Integer orderId, Integer status) {
        return examRecordMapper.updateStatus(orderId,status);
    }

    /**
     * 订单支付成功，更新 status = 1 payTime
     * @param orderId
     * @param status
     * @return
     */
    @Override
    public Boolean paySuccess(Integer orderId, Integer status, Timestamp payTime) {
        return examRecordMapper.paySuccess(orderId,status,payTime);
    }

    /**
     * 医生修改患者检查状态-完成
     * @param dto
     * @return
     */
    @Override
    public Result checkFinished(ExamRecordDto dto) {
        if(dto.getId() != null){
            boolean i = update(Wrappers.<ExaminationRecord>lambdaUpdate()
                    .eq(ExaminationRecord::getId, dto.getId())
                    .set(ExaminationRecord::getStatus, ExamRecordStatusConstant.FINISHED));
            if (i){
                return Result.success();
            }else {
                return Result.error(HttpCodeEnums.SYSTEM_ERROR);
            }
        }else {
            return Result.error(HttpCodeEnums.INFO_IS_BLANK);
        }
    }

    @Autowired
    private PatientMapper patientMapper;

    /**
     * 医生获取当天当班次的检查队列
     * @param dto
     * @return
     */
    @Override
    public Result<List<Queue<ExaminationRecordVO>>> getQueues(QueueDto dto) {
        LocalDate today = LocalDate.now();
        // 前端点击开始叫号，传来doctorId和currentShift
        if(dto.getDoctorId() != null && dto.getCurrentShift() != null){
            //初始化队列
            ExamQueueManager queueManager = new ExamQueueManager(dto.getCurrentShift());

            List<ExaminationRecord> list = new ArrayList<>();
            if(dto.getCurrentShift() == 0){ //上午班 获取timeSlot小于6的record
                list = list(Wrappers.<ExaminationRecord>lambdaQuery()
                        .eq(ExaminationRecord::getCheckDoctorId, dto.getDoctorId())
                        .eq(ExaminationRecord::getDate, today)
                        // 使用.or连接多个条件
                        .and(wrapper -> wrapper
                                .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.PAID)
                                .or()
                                .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.FINISHED))
                        .lt(ExaminationRecord::getTimeSlot,6)
                        .orderByAsc(ExaminationRecord::getTimeSlot));
            }
            if(dto.getCurrentShift() == 1){ //下午班 获取timeSlot大于等于6的record
                list = list(Wrappers.<ExaminationRecord>lambdaQuery()
                        .eq(ExaminationRecord::getCheckDoctorId, dto.getDoctorId())
                        .eq(ExaminationRecord::getDate, today)
                        // 使用.or连接多个条件
                        .and(wrapper -> wrapper
                                .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.PAID)
                                .or()
                                .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.FINISHED))
                        .ge(ExaminationRecord::getTimeSlot,6)
                        .orderByAsc(ExaminationRecord::getTimeSlot));
            }
            // 2 将list中的patientId获取出组成patientIdList
            List<Integer> patientIdList = list.stream()
                    .map(ExaminationRecord::getPatientId).collect(Collectors.toList());

            if(patientIdList.isEmpty()){
                return Result.success();
            }

            // 3 查询出patientList
            List<Patient> patientList = patientMapper.selectBatchIds(patientIdList);

            // 4 将 patientList 中的 id 和 name 封装成map,提高查询性能
            Map<Integer,String> map = patientList.stream()
                    .collect(Collectors.toMap(Patient::getId,Patient::getName));

            // 5 封装成voList
            List<ExaminationRecordVO> voList = new ArrayList<>();
            for(ExaminationRecord record : list){
                String patientName = map.get(record.getPatientId());
                ExaminationRecordVO newOne = new ExaminationRecordVO();
                BeanUtils.copyProperties(record,newOne);
                newOne.setPatientName(patientName);
                voList.add(newOne);
            }

            // 6 封装成queue
            for(ExaminationRecordVO voRecord : voList){
                queueManager.addRecordToNormalQueue(voRecord.getTimeSlot(), voRecord);
            }

            return Result.success(queueManager.getNormalQueues());
        }else {
            return Result.error(HttpCodeEnums.SYSTEM_ERROR);
        }
    }

    @Autowired
    private ClinicMapper clinicMapper;

    /**
     * 管理员获取挂号检查 - 数据分析
     * @param dto
     * @return
     */
    @Override
    public Result<List<DataVO>> getRegData(DataDto dto) {
        if(dto.getClinicIdList() != null){
            List<ExaminationRecord> list = examRecordMapper.getListByClinicIdList(dto.getClinicIdList());
            List<DataVO> voList = new ArrayList<>();
            for(ExaminationRecord record : list){
                Clinic clinic = clinicMapper.selectById(record.getClinicId());
                DataVO newOne = new DataVO();
                newOne.setId(record.getId());
                newOne.setClinicName(clinic.getName());
                newOne.setClinicId(record.getClinicId());
                newOne.setDate(record.getDate());
                voList.add(newOne);
            }
            return Result.success(voList);
        }else {
            return Result.error(HttpCodeEnums.DATA_NOT_EXIST);
        }
    }

    /**
     * 管理员获取未就诊检查记录
     * @return
     */
    @Override
    public Result<List<AlertPaidVO>> getPaidData() {
        List<ExaminationRecord> list = list(Wrappers.<ExaminationRecord>lambdaQuery()
                .eq(ExaminationRecord::getStatus, ExamRecordStatusConstant.PAID));
        List<AlertPaidVO> voList = new ArrayList<>();
        for(ExaminationRecord record : list){
            Patient patient = patientMapper.selectById(record.getPatientId());
            ExaminationItem examinationItem = examItemMapper.selectById(record.getExamItemId());
            AlertPaidVO alertPaidVO = new AlertPaidVO();
            BeanUtils.copyProperties(record,alertPaidVO);
            alertPaidVO.setPhone(patient.getPhone());
            alertPaidVO.setName(patient.getName());
            alertPaidVO.setExamItemName(examinationItem.getName());
            voList.add(alertPaidVO);
        }
        return Result.success(voList);
    }

    /**
     * 自动处理患者过期检查预约
     */
    @Override
    public void handleExpired() {
        update(Wrappers.<ExaminationRecord>lambdaUpdate()
                .lt(ExaminationRecord::getDate, LocalDate.now())
                .set(ExaminationRecord::getStatus, ExamRecordStatusConstant.CANCELED));
    }
}
